package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.external.ExternalInterface;
	import flash.net.FileReference;
	import flash.printing.PrintJob;
	import flash.printing.PrintJobOptions;
	import flash.printing.PrintJobOrientation;
	import flash.system.Security;
	import flash.utils.ByteArray;
	import org.alivepdf.images.ColorSpace;
	import org.alivepdf.images.DoJPEGImage;
	import org.alivepdf.images.DoPNGImage;
	import org.alivepdf.images.PDFImage;
	import org.alivepdf.layout.Mode;
	import org.alivepdf.layout.Orientation;
	import org.alivepdf.layout.Position;
	import org.alivepdf.layout.Resize;
	import org.alivepdf.layout.Size;
	import org.alivepdf.layout.Unit;
	import org.alivepdf.pdf.PDF;
	import org.aszip.compression.CompressionMethod;
	import org.alivepdf.saving.Method;
	import org.aszip.zip.ASZip;
	/**
	 * ...
	 * @author Hatshepsout
	 */
	public class Main extends Sprite
	{
		[Embed(source = "../data/ui/save.png")]
		public var saveIcon:Class;
		
		[Embed(source = "../data/ui/printer.gif")]
		public var printIcon:Class;
		
		private var _saveBtn:Sprite;
		private var _printBtn:Sprite;
		private var _data:Vector.<Object>;
		private var _bmpList:Vector.<Bitmap>;
		
		public function Main() 
		{
			var y:int = 0;
			
			_saveBtn = addChild( new Sprite() ) as Sprite;
			_printBtn = addChild( new Sprite() ) as Sprite;
			_saveBtn.addChild( new saveIcon() as Bitmap );
			_printBtn.addChild( new printIcon() as Bitmap );
			_printBtn.x = _saveBtn.width + 5;
			
			y = Math.max(_printBtn.height, _saveBtn.height);
			
			
			_saveBtn.y = y - _saveBtn.height;
			_printBtn.y = y - _printBtn.height;
			
			
			if ( ExternalInterface.available == true )
			{
				Security.allowDomain("localhost");
			}
			
			_saveBtn.addEventListener(MouseEvent.CLICK, _saveHandler );
			_printBtn.addEventListener(MouseEvent.CLICK, _printHandler );
		}
		
	
		private function _getData():Vector.<Object>
		{
			var obj:Array = ExternalInterface.call("getExport") as Array;
			var data:String = null;
			var i:int = obj.length;
			var by:ByteArray = null;
			var export:Object = null;
			var list:Vector.<Object> = new Vector.<Object>();
			var desc:Object = new Object();
			
			while ( --i > -1 )
			{
				export = obj[i];
				data = export.imgData as String;
				desc = new Object();
				desc.data = Base64.decodeToByteArray(data.slice( data.indexOf("base64,") + 7 ));
				desc.name = _cleanify(export.name);
				desc.width = export.width;
				desc.height = export.height;
				
				list.push(desc);
			}
			
			return list;
		}
		
		private function _cleanify(name:String):String
		{
			var chars:Array = ["°", ",", " "];
			var i:int = chars.length;
			while ( --i > -1 )
			{
				while ( name.indexOf(chars[i]) > -1 )
				{
					name = name.replace(chars[i], "_");
				}
			}
			
			return name;
		}
		
		private function _log(value:String):void
		{
			ExternalInterface.call("trace", value);
		}
		
		
		/*download images and pdf into a zip file*/
		private function _saveHandler(e:MouseEvent):void 
		{
			var isPDF:Boolean = ExternalInterface.call("isPDF") as Boolean;
			var file:FileReference = new FileReference();
			var myZip:ASZip = new ASZip (CompressionMethod.NONE);
			var myZipFile:ByteArray = null;
			var data:Vector.<Object> = _getData();
			var i:int = data.length;
			var export:Object = null;
			var by:ByteArray = null;
			var image:PDFImage;
			var doc:PDF = null;
			var bmpData:BitmapData = null;
			
			myZip.addDirectory ("images/");
			
			while ( --i > -1 )
			{
				export = data[i];				
				by = export.data as ByteArray;
				by.position = 0;
				
				if ( isPDF == true )
				{
					doc = new PDF(Orientation.PORTRAIT, Unit.MM, Size.A4);
					doc.addPage();
					
					bmpData = new BitmapData(export.width, export.height, true, 0x00000000);
					
					if ( String(export.name).indexOf(".png") > -1 )
					{
						//image = new DoPNGImage( bmpData, by, i );
						//ExternalInterface.call("noPngForPDF");
						//return;
						
						bmpData = PNGDecoder.decodeImage(by);
						doc.addImage( new Bitmap(bmpData), new Resize(Mode.RESIZE_PAGE, Position.CENTERED) );
					}
					else
					{
						image = new DoJPEGImage( bmpData , by, i );
					}
					
					try
					{
						doc.addImageStream(	image.bytes, 
											ColorSpace.DEVICE_RGB, 
											new Resize(Mode.RESIZE_PAGE, Position.CENTERED));
					}
					catch (e:Error)
					{
						_log(e.message);
					}
										
					by = doc.save(Method.LOCAL) as ByteArray;
					by.position = 0;
					myZip.addFile ( by, "images/" + export.name + ".pdf");
				}
				else
				{
					myZip.addFile ( by, "images/" + export.name);
				}
			}
			
			myZipFile = myZip.saveZIP ( "local" );
			
			if ( data.length == 1 && by != null )
			{
				if ( isPDF == false )
				{
					file.save(by, export.name);
				}
				else
				{
					file.save(by, export.name + '.pdf');
				}
			}
			else 
			{
				file.save(myZipFile, "export.zip");
			}
			
		}
		
		
		/*print all images*/
		private function _printHandler(e:MouseEvent):void
		{
			var isPDF:Boolean = ExternalInterface.call("isPDF") as Boolean;
			
			if ( isPDF == true )
			{
				ExternalInterface.call("noPrintPDF");
				return;
			}
			
			_data = _getData();
			_bmpList = new Vector.<Bitmap>();
			_loadNextBitmap();
		}
		
		private function _printAll():void 
		{
			var frame:Sprite = null;
			var myPrintJob:PrintJob = new PrintJob();
            var options:PrintJobOptions = new PrintJobOptions();
			var ratio:Number = 1;
			var i:int = _bmpList.length;
			var bitmap:Bitmap = null;
			var rotate:Boolean = false;
			var y:int = 0;
			
			options.printAsBitmap = true;
			myPrintJob.start();
			
			while ( --i > -1 )
			{			
				bitmap = _bmpList[i];
				frame = addChild( new Sprite() ) as Sprite;
				frame.addChild(bitmap);
				frame.y = y;
				frame.x = 100;
				
				addChild(frame);
				
				ratio = myPrintJob.pageWidth / bitmap.width;
				bitmap.scaleX = bitmap.scaleY = ratio;
				y += bitmap.height * bitmap.scaleY;
				
				
				myPrintJob.addPage(frame, null, options);
			}
			
			myPrintJob.send();
		}
	
		private function _loadNextBitmap():void
		{
			var obj:Object = null;
			var loader:Loader = null;
			if ( _data.length == 0 )
			{
				_printAll();
			}
			else
			{
				obj = _data.shift();
				loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _loadBmpHandler);
				loader.loadBytes(obj.data as ByteArray);
			}
		}
		
		private function _loadBmpHandler(e:Event):void 
		{
			var info:LoaderInfo = e.target as LoaderInfo;
			var loader:Loader = info.loader;
			
			info.removeEventListener(Event.COMPLETE, _loadBmpHandler);
			_bmpList.push( loader.content as Bitmap );
			_loadNextBitmap();
		}
		
	}

}